//
// Created by hay boy on 2022/7/15.
//

#ifndef ALGORITHMS_UNLZW_H
#define ALGORITHMS_UNLZW_H
#include <fstream>
#include <iostream>
#include <cstring>

using namespace std;
typedef pair<int,char> pairType;
const int MAX_CODES = 4096,BYTE_SIZE = 8,EXCESS = 4,ALPHA = 256,MASK = 15;
pairType ht[MAX_CODES];
char s[MAX_CODES];
int size;
int leftOver;
bool bitsLeftOver = false;
ifstream in;
ofstream out;
void setFiles_unlzw(int argc,char* argv[]){
    char inputFile[54];
    if(argc>=2){
        strcpy(inputFile,argv[1]);
    }else{
        cout<<"Enter name of file to decompress"<<endl;
        cin>>inputFile;
    }
    in.open(inputFile,ios::binary);
    if(in.fail()){
        cerr<<"Cannot open "<<inputFile<<endl;
        exit(1);
    }
    string outFileName = string(inputFile);
    outFileName = "2"+string(outFileName.begin(), outFileName.begin() + outFileName.find_last_of('.'));
    out.open(outFileName, ios::binary);
}
void output_unlzw(int code){
    size = -1;
    while(code>=ALPHA){
        s[++size] = ht[code].second;
        code = ht[code].first;
    }
    s[++size] = code;
    for(int i = size;i>=0;i--){
//        cout<<(int)s[i]<<endl;
        out.put(s[i]);
    }
}
bool getCode(int &code){
    int c,d;
    if((c=in.get())==EOF){
        return false;
    }
    if(bitsLeftOver){
        code = (leftOver<<BYTE_SIZE)|c;
    }else{
        d = in.get();
        code = (c<<EXCESS)|(d>>EXCESS);
        leftOver = d&MASK;
    }
    bitsLeftOver = !bitsLeftOver;
    cout<<code<<endl;
    return true;
}
void decompress(){
    int codesUsed = ALPHA;
    int pcode,ccode;
    if(getCode(pcode)){
        s[0] = pcode;
//        cout<<(int)s[0]<<endl;
        out.put(s[0]);
        size = 0;
        while(getCode(ccode)){
            if(ccode<codesUsed){
                //字典隐式存在这个词条
                //ccode 为12位有效的数字
                output_unlzw(ccode);
                if(codesUsed<MAX_CODES){
                    ht[codesUsed].first = pcode;
                    ht[codesUsed++].second = s[size];
                }
            }else{
//                ccode==codesUsed 还没有这个词条
//                code > codesUsed
                ht[codesUsed].first = pcode;
                ht[codesUsed++].second = s[size];
                output_unlzw(ccode);
            }
            pcode = ccode;
        }
    }
    out.close();
    in.close();
}
#endif //ALGORITHMS_UNLZW_H
